package com.reyco1.medusa.manager
{
	import com.reyco1.medusa.util.Delegate;
	
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.display.Stage;
	import flash.events.MouseEvent;
	import flash.geom.Rectangle;
	import flash.utils.Dictionary;

	public class DragManager
	{
		public static var draggableObjects:Dictionary = new Dictionary();
		public static var isDraggin:Boolean = false;
		
		private static var currentDragObject:Sprite;
		
		public static function allowDrag(displayObj:DisplayObject, dragRect:Rectangle = null, snapToCenter:Boolean = false, 
										 proxyObject:DisplayObject = null, releaseCallback:Function = null, releaseCallbackParams:Array = null,
										 onUpdate:Function = null, onUpdateParams:Array = null):void
		{
			displayObj.addEventListener(MouseEvent.MOUSE_DOWN, doDrag);
			draggableObjects[displayObj.name] = {target:displayObj, dragRect:dragRect, snapToCenter:snapToCenter, proxyObject:proxyObject, 
				releaseCallback:releaseCallback, releaseCallbackParams:releaseCallbackParams, onUpdate:onUpdate, onUpdateParams:onUpdateParams};
		}
		
		public static function unallowDrag(displayObj:Sprite):void
		{
			displayObj.removeEventListener(MouseEvent.MOUSE_DOWN, DragManager.doDrag);
			delete draggableObjects[displayObj];
		}
		
		public static function clear():void
		{
			for each(var key:Object in draggableObjects)
			{
				var targetProps:Object = draggableObjects[key];
				var target:Sprite = draggableObjects[key].target;
				unallowDrag(target);
			}
		}
		
		private static function doDrag(e:MouseEvent):void
		{
			if(!e.ctrlKey && !e.shiftKey)
			{
				var target:Sprite = e.currentTarget as Sprite;
				currentDragObject = target;
				
				var targetProps:Object = draggableObjects[target.name];
				target = targetProps.proxyObject != null ? targetProps.proxyObject : target;
				targetProps.stage = target.stage
				
				target.startDrag(targetProps.snapToCenter, targetProps.dragRect);
				target.stage.addEventListener(MouseEvent.MOUSE_UP, DragManager.removeDrag);
				target.stage.addEventListener(MouseEvent.MOUSE_MOVE, DragManager.handleMove);
				
				isDraggin = true;
			}
		}
		
		private static function handleMove(e:MouseEvent):void
		{
			var targetProps:Object = draggableObjects[currentDragObject.name];
			
			if(targetProps.onUpdate) Delegate.execute(targetProps.onUpdate, targetProps.onUpdateParams);
			
			e.updateAfterEvent();
		}
		
		private static function removeDrag(e:MouseEvent):void
		{
			var target:Sprite;
			var targetProps:Object = draggableObjects[currentDragObject.name];
			target = Sprite(targetProps.proxyObject != null ? targetProps.proxyObject : currentDragObject);
			
			target.stage.removeEventListener(MouseEvent.MOUSE_UP, DragManager.removeDrag);
			target.stage.removeEventListener(MouseEvent.MOUSE_MOVE, DragManager.handleMove);
			target.stopDrag();	
			
			if(targetProps.releaseCallback != null && targetProps.releaseCallbackParams == null) 
				targetProps.releaseCallback.call();
			if(targetProps.releaseCallback != null && targetProps.releaseCallbackParams != null) 
				targetProps.releaseCallback.apply(null, targetProps.releaseCallbackParams);
			
			isDraggin = false;
		}
	}
}